package com.etone.smartAudit.service;

import com.alibaba.fastjson.JSON;
import com.etone.smartAudit.domain.Admin;
import com.etone.smartAudit.domain.AuditExceptionMonth;
import com.etone.smartAudit.domain.EmailRecord;
import com.etone.smartAudit.dto.email.AuditExceptionEmailDTO;
import com.etone.smartAudit.dto.email.EmailDTO;
import com.etone.smartAudit.vo.FileVO;
import com.etone.smartAudit.vo.auditException.AuditExceptionByteArrayOutputStream;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.mail.internet.MimeUtility;
import java.io.File;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: 蒋学伟
 * @create: 2020-07-06 10:13:06
 * @Description EmailService
 */
@Log4j2
@Service
public class EmailService {
    @Autowired
    private JavaMailSenderImpl mailSender;

    @Autowired
    private AuditExceptionService auditExceptionService;

    @Autowired
    private EmailRecordService emailRecordService;

    @Value("${spring.mail.username}")
    private String from;

    @Value("${audit.filePath}")
    private String filePath;

    /**
     * 发送邮件
     *
     * @param emailDTO
     * @param admin
     */
    public void sent(EmailDTO emailDTO, Admin admin) {
        Boolean isSuccess = Boolean.TRUE;
        MimeMessageHelper message = null;
        try {
            message = new MimeMessageHelper(mailSender.createMimeMessage(), true);
            message.setFrom(from);
            message.setTo(emailDTO.getTo().toArray(new String[emailDTO.getTo().size()]));
            if (!CollectionUtils.isEmpty(emailDTO.getCc())) {
                message.setCc(emailDTO.getCc().toArray(new String[emailDTO.getCc().size()]));
            }
            message.setSubject(emailDTO.getSubject());
            message.setText(emailDTO.getContent());

            //附件
            mailSender.send(message.getMimeMessage());
        } catch (Exception e) {
            isSuccess = Boolean.FALSE;
            e.printStackTrace();
        } finally {
            doSendAfter(emailDTO, null, isSuccess, admin);
        }

    }

    public void sentFile(EmailDTO emailDTO, List<File> files, Admin admin) {
        Boolean isSuccess = Boolean.TRUE;
        MimeMessageHelper message = null;
        try {
            message = new MimeMessageHelper(mailSender.createMimeMessage(), true, "utf-8");
            message.setFrom(from);
            message.setTo(emailDTO.getTo().toArray(new String[emailDTO.getTo().size()]));
            if (!CollectionUtils.isEmpty(emailDTO.getCc())) {
                message.setCc(emailDTO.getCc().toArray(new String[emailDTO.getCc().size()]));
            }
            message.setSubject(emailDTO.getSubject());
            message.setText(emailDTO.getContent());
            for (File file : files) {
                if (file != null && file.exists()) {
                    message.addAttachment(MimeUtility.encodeWord(file.getName(), "utf-8", "B"), file);
                }
            }
            mailSender.send(message.getMimeMessage());
        } catch (Exception e) {
            isSuccess = Boolean.FALSE;
            e.printStackTrace();
        } finally {
            doSendAfter(emailDTO, files, isSuccess, admin);
        }
    }


    /**
     * 附件流
     *
     * @param emailDTO               邮件信息
     * @param byteArrayOutputStreams 附件流
     */
    public void sent(EmailDTO emailDTO, List<AuditExceptionByteArrayOutputStream> byteArrayOutputStreams) {
        MimeMessageHelper message = null;
        try {
            message = new MimeMessageHelper(mailSender.createMimeMessage(), true);
            message.setFrom(from);
            message.setTo(emailDTO.getTo().toArray(new String[emailDTO.getTo().size()]));
            if (!CollectionUtils.isEmpty(emailDTO.getCc())) {
                message.setCc(emailDTO.getCc().toArray(new String[emailDTO.getCc().size()]));
            }
            message.setSubject(emailDTO.getSubject());
            message.setText(emailDTO.getContent());

            //附件
            if (!CollectionUtils.isEmpty(byteArrayOutputStreams)) {
                for (int i = 0; i < byteArrayOutputStreams.size(); i++) {
                    AuditExceptionByteArrayOutputStream byteArrayOutputStream = byteArrayOutputStreams.get(i);
                    message.addAttachment(byteArrayOutputStream.getFileName(), new ByteArrayResource(byteArrayOutputStream.toByteArray()));
                    byteArrayOutputStream.close();
                }
            }
            mailSender.send(message.getMimeMessage());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送审计异常邮件
     *
     * @param emailDTO
     * @param admin
     */
    public void auditExceptionSend(AuditExceptionEmailDTO emailDTO, Admin admin) {
        List<Integer> auditExceptionIds = emailDTO.getAuditExceptionIds();
        List<AuditExceptionMonth> auditExceptionMonths = auditExceptionService.selectBatchIds(auditExceptionIds);
        List<File> files = auditExceptionMonths.stream().map(auditExceptionMonth -> {
            FileVO fileVO = JSON.parseObject(auditExceptionMonth.getLocalFile(), FileVO.class);

            return new File(filePath + "/" + fileVO.getUrl());

        }).collect(Collectors.toList());
        sentFile(emailDTO, files, admin);
    }

    /**
     * 发送成功或者失败的操作
     *
     * @param emailDTO
     * @param files
     * @param isSuccess
     * @param admin
     */
    public void doSendAfter(EmailDTO emailDTO, List<File> files, Boolean isSuccess, Admin admin) {
        //保存记录
        emailRecordService.save(
                EmailRecord
                        .builder()
                        .to(CollectionUtils.isEmpty(emailDTO.getTo()) ? "未知" : emailDTO.getTo().stream().collect(Collectors.joining(",")))
                        .cc(CollectionUtils.isEmpty(emailDTO.getCc()) ? null : emailDTO.getCc().stream().collect(Collectors.joining(",")))
                        .content(emailDTO.getContent())
                        .createTime(new Date())
                        .fileNames(CollectionUtils.isEmpty(files) ? null : files.stream().map(File::getName).collect(Collectors.joining(",")))
                        .hasFile(!CollectionUtils.isEmpty(files))
                        .isSuccess(isSuccess)
                        .subject(emailDTO.getSubject())
                        .createAdminId(admin.getId())
                        .build()
        );
    }
}
